/*
**  Copyright (c) 2014 Michael Liu(michael.liu.point@gmail.com).
**
**  Project: Gateway Unified Management Platform
**  File:    mtk7620.c
**  Author:  Michael
**  Date:    06/22/2014
**
**  Purpose:
**    MTK7620 depend function implement.
*/

/* Include files. */

#include "common.h"
#include "pfdep.h"

#include "mtk7620_local.h"

/* Macro constant definitions. */

/* Type definitions. */

/* Local function declarations. */

static e_ret check_load_file_format(char *filename);
static e_ret set_tz_to_cfgfile(const unsigned int timezone);
static e_ret get_fm_info(char *fm_name, tversion * fw_info);
static e_ret fm_info_check(tsys_admin * sa, tversion * fota_info);
static e_ret mtd_write_firmware(char *filename, char *offset, char *len, char *mtdname);
static e_ret getFileSize(char *filename, int *len);
static e_ret do_upgrade(tsys_admin * sa, char *fw_file);
static void *do_start_fota_upgrade(void *arg);
static void *do_check_fotainfo();
static e_ret fm_upgrade_check(tsys_admin * sa, tversion * fota_info, char *fw_file);

/* External function declarations. */

extern e_ret pf_dep_sa_devs_init(tsys_admin * sa);
extern e_ret pf_dep_sa_devs_setup(tsys_admin * sa);

extern e_ret pf_dep_dp_devs_init(tdata_paths * dp);
extern e_ret pf_dep_dp_rules_init(tdata_paths * dp);
extern e_ret pf_dep_dp_ifs_init(tdata_paths * dp);
extern e_ret pf_dep_dp_ifs_setup(tdata_paths * dp);
extern e_ret pf_dep_dp_rules_setup(tdata_paths * dp);
extern unsigned long crc32(unsigned long crc, const char *buf, unsigned int len);

/* Macro API definitions. */

/* Global variable declarations. */
static COUNTRY_CODE_TO_COUNTRY_REGION allCountry[] = {
/* {Country Number, ISO Name, Country Name, Support 11A, 11A Country Region, Support 11G, 11G Country Region} */
	{0, "DB", "Debug", eBOOL_TRUE, A_BAND_REGION_7, eBOOL_TRUE, G_BAND_REGION_5},
	{8, "AL", "ALBANIA", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{12, "DZ", "ALGERIA", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{32, "AR", "ARGENTINA", eBOOL_TRUE, A_BAND_REGION_3, eBOOL_TRUE, G_BAND_REGION_1},
	{51, "AM", "ARMENIA", eBOOL_TRUE, A_BAND_REGION_2, eBOOL_TRUE, G_BAND_REGION_1},
	{36, "AU", "AUSTRALIA", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{40, "AT", "AUSTRIA", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{31, "AZ", "AZERBAIJAN", eBOOL_TRUE, A_BAND_REGION_2, eBOOL_TRUE, G_BAND_REGION_1},
	{48, "BH", "BAHRAIN", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{112, "BY", "BELARUS", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{56, "BE", "BELGIUM", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{84, "BZ", "BELIZE", eBOOL_TRUE, A_BAND_REGION_4, eBOOL_TRUE, G_BAND_REGION_1},
	{68, "BO", "BOLIVIA", eBOOL_TRUE, A_BAND_REGION_4, eBOOL_TRUE, G_BAND_REGION_1},
	{76, "BR", "BRAZIL", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{96, "BN", "BRUNEI DARUSSALAM", eBOOL_TRUE, A_BAND_REGION_4, eBOOL_TRUE, G_BAND_REGION_1},
	{100, "BG", "BULGARIA", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{124, "CA", "CANADA", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_0},
	{152, "CL", "CHILE", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{156, "CN", "CHINA", eBOOL_TRUE, A_BAND_REGION_4, eBOOL_TRUE, G_BAND_REGION_1},
	{170, "CO", "COLOMBIA", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_0},
	{188, "CR", "COSTA RICA", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{191, "HR", "CROATIA", eBOOL_TRUE, A_BAND_REGION_2, eBOOL_TRUE, G_BAND_REGION_1},
	{196, "CY", "CYPRUS", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{203, "CZ", "CZECH REPUBLIC", eBOOL_TRUE, A_BAND_REGION_2, eBOOL_TRUE, G_BAND_REGION_1},
	{208, "DK", "DENMARK", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{214, "DO", "DOMINICAN REPUBLIC", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_0},
	{218, "EC", "ECUADOR", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{818, "EG", "EGYPT", eBOOL_TRUE, A_BAND_REGION_2, eBOOL_TRUE, G_BAND_REGION_1},
	{222, "SV", "EL SALVADOR", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{233, "EE", "ESTONIA", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{246, "FI", "FINLAND", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{250, "FR", "FRANCE", eBOOL_TRUE, A_BAND_REGION_2, eBOOL_TRUE, G_BAND_REGION_1},
	{268, "GE", "GEORGIA", eBOOL_TRUE, A_BAND_REGION_2, eBOOL_TRUE, G_BAND_REGION_1},
	{276, "DE", "GERMANY", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{300, "GR", "GREECE", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{320, "GT", "GUATEMALA", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_0},
	{340, "HN", "HONDURAS", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{344, "HK", "HONG KONG", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{348, "HU", "HUNGARY", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{352, "IS", "ICELAND", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{356, "IN", "INDIA", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{360, "ID", "INDONESIA", eBOOL_TRUE, A_BAND_REGION_4, eBOOL_TRUE, G_BAND_REGION_1},
	{364, "IR", "IRAN", eBOOL_TRUE, A_BAND_REGION_4, eBOOL_TRUE, G_BAND_REGION_1},
	{372, "IE", "IRELAND", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{376, "IL", "ISRAEL", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{380, "IT", "ITALY", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{392, "JP", "JAPAN", eBOOL_TRUE, A_BAND_REGION_9, eBOOL_TRUE, G_BAND_REGION_1},
	{400, "JO", "JORDAN", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{398, "KZ", "KAZAKHSTAN", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{408, "KP", "KOREA DEMOCRATIC PEOPLE'S REPUBLIC OF", eBOOL_TRUE, A_BAND_REGION_5, eBOOL_TRUE, G_BAND_REGION_1},
	{410, "KR", "KOREA REPUBLIC OF", eBOOL_TRUE, A_BAND_REGION_5, eBOOL_TRUE, G_BAND_REGION_1},
	{414, "KW", "KUWAIT", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{428, "LV", "LATVIA", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{422, "LB", "LEBANON", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{438, "LI", "LIECHTENSTEIN", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{440, "LT", "LITHUANIA", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{442, "LU", "LUXEMBOURG", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{446, "MO", "MACAU", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{807, "MK", "MACEDONIA", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{458, "MY", "MALAYSIA", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{484, "MX", "MEXICO", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_0},
	{492, "MC", "MONACO", eBOOL_TRUE, A_BAND_REGION_2, eBOOL_TRUE, G_BAND_REGION_1},
	{504, "MA", "MOROCCO", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{528, "NL", "NETHERLANDS", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{554, "NZ", "NEW ZEALAND", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{578, "NO", "NORWAY", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_0},
	{512, "OM", "OMAN", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{586, "PK", "PAKISTAN", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{591, "PA", "PANAMA", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_0},
	{604, "PE", "PERU", eBOOL_TRUE, A_BAND_REGION_4, eBOOL_TRUE, G_BAND_REGION_1},
	{608, "PH", "PHILIPPINES", eBOOL_TRUE, A_BAND_REGION_4, eBOOL_TRUE, G_BAND_REGION_1},
	{616, "PL", "POLAND", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{620, "PT", "PORTUGAL", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{630, "PR", "PUERTO RICO", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_0},
	{634, "QA", "QATAR", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{642, "RO", "ROMANIA", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{643, "RU", "RUSSIA FEDERATION", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{682, "SA", "SAUDI ARABIA", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{702, "SG", "SINGAPORE", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{703, "SK", "SLOVAKIA", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{705, "SI", "SLOVENIA", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{710, "ZA", "SOUTH AFRICA", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{724, "ES", "SPAIN", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{752, "SE", "SWEDEN", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{756, "CH", "SWITZERLAND", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{760, "SY", "SYRIAN ARAB REPUBLIC", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{158, "TW", "TAIWAN", eBOOL_TRUE, A_BAND_REGION_3, eBOOL_TRUE, G_BAND_REGION_0},
	{764, "TH", "THAILAND", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{780, "TT", "TRINIDAD AND TOBAGO", eBOOL_TRUE, A_BAND_REGION_2, eBOOL_TRUE, G_BAND_REGION_1},
	{788, "TN", "TUNISIA", eBOOL_TRUE, A_BAND_REGION_2, eBOOL_TRUE, G_BAND_REGION_1},
	{792, "TR", "TURKEY", eBOOL_TRUE, A_BAND_REGION_2, eBOOL_TRUE, G_BAND_REGION_1},
	{804, "UA", "UKRAINE", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{784, "AE", "UNITED ARAB EMIRATES", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{826, "GB", "UNITED KINGDOM", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_1},
	{840, "US", "UNITED STATES", eBOOL_TRUE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_0},
	{858, "UY", "URUGUAY", eBOOL_TRUE, A_BAND_REGION_5, eBOOL_TRUE, G_BAND_REGION_1},
	{860, "UZ", "UZBEKISTAN", eBOOL_TRUE, A_BAND_REGION_1, eBOOL_TRUE, G_BAND_REGION_0},
	{862, "VE", "VENEZUELA", eBOOL_TRUE, A_BAND_REGION_5, eBOOL_TRUE, G_BAND_REGION_1},
	{704, "VN", "VIET NAM", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{887, "YE", "YEMEN", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{716, "ZW", "ZIMBABWE", eBOOL_FALSE, A_BAND_REGION_0, eBOOL_TRUE, G_BAND_REGION_1},
	{999, "", "", 0, 0, 0, 0}
};

//static char download_name_cfgfile[PF_DEP_DOWNLOAD_NAME_SIZE];
static char download_name_fw[PF_DEP_DOWNLOAD_NAME_SIZE];
#define NUM_OF_COUNTRIES	(sizeof(allCountry)/sizeof(COUNTRY_CODE_TO_COUNTRY_REGION))

static tdata_paths sys_dp;
static tsys_admin sys_sa;

static tos_dep_mutex fm_download_mutex;
static int lock_fm = 1;

unsigned char dev_mode = eDP_MODE_BRIDGE_REPEATER;

e_ret pf_dep_dp_setup(void)
{

	e_ret ret;

	ret = pf_dep_dp_devs_init(&sys_dp);
	if (ret != eRET_SUCCESS) {
		sysmgr_err("pf_dep_dp_devs_init() failed, ret: %d.\n", ret);
		return (ret);
	}

	ret = pf_dep_dp_ifs_init(&sys_dp);
	if (ret != eRET_SUCCESS) {
		sysmgr_err("pf_dep_dp_ifs_init() failed, ret: %d.\n", ret);
		return (ret);
	}

	ret = pf_dep_dp_rules_init(&sys_dp);
	if (ret != eRET_SUCCESS) {
		sysmgr_err("pf_dep_dp_rules_init() failed, ret: %d.\n", ret);
		return (ret);
	}

	ret = data_path_init(&sys_dp);
	if (ret != eRET_SUCCESS) {
		sysmgr_err("data_path_init() failed, ret: %d.\n", ret);
		return (ret);
	}

	ret = pf_dep_dp_ifs_setup(&sys_dp);
	if (ret != eRET_SUCCESS) {
		sysmgr_err("pf_dep_dp_ifs_setup() failed, ret: %d.\n", ret);
		return (ret);
	}

	ret = pf_dep_dp_rules_setup(&sys_dp);
	if (ret != eRET_SUCCESS) {
		sysmgr_err("pf_dep_dp_rules_setup() failed, ret: %d.\n", ret);
		return (ret);
	}

	return (eRET_SUCCESS);
}

e_ret pf_dep_sa_setup(void)
{

	e_ret ret;
	int tz;

	memset(&sys_sa, 0, sizeof(sys_sa));

	pf_dep_get_fminfo(&sys_sa.fw_info);
	pf_dep_get_ntp(sys_sa.ntp_server);
	pf_dep_get_timezone(&tz);
	pf_dep_set_timezone(tz);

	ret = pf_dep_sa_devs_init(&sys_sa);
	if (ret != eRET_SUCCESS) {
		sysmgr_err("pf_dep_sa_devs_init() failed, ret: %d.\n", ret);
		return (ret);
	}

	ret = sys_admin_init(&sys_sa);
	if (ret != eRET_SUCCESS) {
		sysmgr_err("sys_admin_init() failed, ret: %d.\n", ret);
		return (ret);
	}

	ret = pf_dep_sa_devs_setup(&sys_sa);
	if (ret != eRET_SUCCESS) {
		sysmgr_err("pf_dep_sa_devs_init() failed, ret: %d.\n", ret);
		return (ret);
	}

	return (eRET_SUCCESS);
}

e_ret pf_dep_cfg_init(void)
{

	nvram_init(RT2860_NVRAM);
	nvram_init(RTDEV_NVRAM);

	return (eRET_SUCCESS);

}

e_ret pf_dep_cfg_close(void)
{

	nvram_close(RT2860_NVRAM);
	nvram_close(RTDEV_NVRAM);

	return (eRET_SUCCESS);
}

e_ret pf_dep_cfg_check(void)
{

	const char *val;
	e_bool invalid;

	/* Check if flash value is valid. */

	nvram_init(RT2860_NVRAM);
	val = pf_dep_cfg_get_val(RT2860_NVRAM, NVRAM_CFG_CHECK_KEY, "");
	invalid = (val[0] != NVRAM_CFG_CHECK_VAL) ? eBOOL_TRUE : eBOOL_FALSE;
	nvram_close(RT2860_NVRAM);
	if (invalid) {
		sysmgr_err("Config Check: flash[%d] value invalid, reset it.\n", RT2860_NVRAM);
		os_dep_do_system("ralink_init", "clear", "rt2860", NULL);
		os_dep_do_system("ralink_init", "renew", "rt2860", PF_DEP_2860_DEFAULT_SETTING, NULL);
	}

	nvram_init(RTDEV_NVRAM);
	val = pf_dep_cfg_get_val(RTDEV_NVRAM, NVRAM_CFG_CHECK_KEY, "");
	invalid = (val[0] != NVRAM_CFG_CHECK_VAL) ? eBOOL_TRUE : eBOOL_FALSE;
	nvram_close(RTDEV_NVRAM);
	if (invalid) {
		sysmgr_err("Config Check: flash[%d] value invalid, reset it.\n", RTDEV_NVRAM);
		os_dep_do_system("ralink_init", "clear", "rtdev", NULL);
		os_dep_do_system("ralink_init", "renew", "rtdev", PF_DEP_RTDEV_DEFAULT_SETTING, NULL);
	}

	return (eRET_SUCCESS);

}

e_ret pf_dep_cfg_save(void)
{

	nvram_commit(RT2860_NVRAM);
	nvram_commit(RTDEV_NVRAM);

	return (eRET_SUCCESS);

}

e_ret pf_dep_get_fminfo(tversion * fw_info)
{
	e_ret ret;
	ret = get_fm_info(MTD_IMAGE, fw_info);

	sysmgr_dbg("pf_dep_get_fminfo() fwname[%s], ver[%s] ,datetime[%d-%d-%d-%d:%d:%d]\n",
		   fw_info->model, fw_info->version, fw_info->rel_time.year, fw_info->rel_time.month,
		   fw_info->rel_time.day, fw_info->rel_time.hour, fw_info->rel_time.minute, fw_info->rel_time.second);

	return ret;

}

e_ret pf_dep_check_password(const char *password, unsigned char *ok)
{
	const char *val;

	val = pf_dep_cfg_get_val(RT2860_NVRAM, ADMIN_PASSWORD_KEY, "");
	sysmgr_dbg("Check user pswd[%s] ?= [%s]\n", password, val);
	if (val[0] == '\0') {
		*ok = eBOOL_TRUE;
	} else if (strcmp(val, password) == 0) {
		*ok = eBOOL_TRUE;
	}

	return (eRET_SUCCESS);
}

e_ret pf_dep_set_password(const char *password)
{
	pf_dep_cfg_set_val(RT2860_NVRAM, ADMIN_PASSWORD_KEY, (char *)password);
	sysmgr_dbg("Set user pswd -> [%s]\n", password);

	return (eRET_SUCCESS);
}

e_ret pf_dep_get_password(char *password)
{
	const char *val;

	val = pf_dep_cfg_get_val(RT2860_NVRAM, ADMIN_PASSWORD_KEY, "");
	sysmgr_dbg("pf_dep_cfg_get_val() get password -> [%s]\n", val);
	strcpy(password, val);

	return (eRET_SUCCESS);
}

e_ret pf_dep_set_qis(unsigned char qis_done)
{
	if (qis_done) {
		pf_dep_cfg_set_val(RT2860_NVRAM, QIS_DONE_KEY, "1");
		init_lan_br_if_qis_net(eBOOL_TRUE);
	} else {
		pf_dep_cfg_set_val(RT2860_NVRAM, QIS_DONE_KEY, "0");
	}
	return (eRET_SUCCESS);
}

e_ret pf_dep_get_qis(unsigned char *qis_done)
{
	const char *val;

	val = pf_dep_cfg_get_val(RT2860_NVRAM, QIS_DONE_KEY, "0");
	if (val[0] == '1') {
		*qis_done = eBOOL_TRUE;
	} else {
		*qis_done = eBOOL_FALSE;
	}

	return (eRET_SUCCESS);
}

e_ret pf_dep_get_ntp(char *ntpserver)
{
	const char *val;

	val = pf_dep_cfg_get_val(RT2860_NVRAM, NTPSERVERIP, DEFAULT_NTPSERVER);
	strcpy(ntpserver, val);

	return (eRET_SUCCESS);
}

e_ret pf_dep_set_ntp(char *ntpserver)
{
	struct date_time datetime;

	pf_dep_cfg_set_val(RT2860_NVRAM, NTPSERVERIP, ntpserver);
	os_dep_get_datetime(&datetime);
	run_ntpclient_update_time(ntpserver);

	return (eRET_SUCCESS);
}

e_ret pf_dep_set_timezone(const unsigned int timezone)
{
	char val_time_zone[4];
	e_ret ret;

	ret = set_tz_to_cfgfile(timezone);
	if (ret != eRET_SUCCESS) {
		sysmgr_err("set_tz_to_cfgfile()err ret:[%d]\n", ret);
		return ret;
	}
	sprintf(val_time_zone, "%u", timezone);
	pf_dep_cfg_set_val(RT2860_NVRAM, TIMEZONE, val_time_zone);
	sysmgr_dbg("timezone set [%u]\n", timezone);

	return (eRET_SUCCESS);
}

e_ret pf_dep_get_timezone(unsigned int *timezone)
{
	const char *val;

	val = pf_dep_cfg_get_val(RT2860_NVRAM, TIMEZONE, DEFAULT_TZ);
	*timezone = strtol(val, NULL, 10);
	sysmgr_dbg("timezone get [%u]\n", *timezone);

	return (eRET_SUCCESS);
}

e_ret pf_dep_get_language(unsigned char *lang)
{
	const char *val;
	int country_num;

	val = pf_dep_cfg_get_val(RT2860_NVRAM, WEB_UI_LANGUAGE, "0");
	country_num = strtol(val, NULL, 10);
	sysmgr_dbg("Check language get [%u] ?= [%s]\n", country_num, val);
	switch (country_num) {
	case 0:
		*lang = eSYS_MGR_LANG_CHINESE_SIMPLE;
		break;
	case 1:
		*lang = eSYS_MGR_LANG_CHINESE_TRADITIONAL;
		break;
	case 2:
		*lang = eSYS_MGR_LANG_ENGLISH;
		break;
	default:
		*lang = eSYS_MGR_LANG_ENGLISH;
		break;
	}

	return (eRET_SUCCESS);
}

e_ret pf_dep_set_language(unsigned char lang)
{
	char val_country_code[4];

	sprintf(val_country_code, "%u", lang);
	pf_dep_cfg_set_val(RT2860_NVRAM, WEB_UI_LANGUAGE, val_country_code);

	return (eRET_SUCCESS);
}

e_ret pf_dep_reboot()
{
	/* Save config. */
	pf_dep_cfg_close();

	os_dep_do_system("reboot", NULL);
	return (eRET_SUCCESS);
}

e_ret pf_dep_dump_cfg(char *cfg_file)
{

	unlink(PF_DEP_2860_SETTING);
	unlink(PF_DEP_RTDEV_SETTING);
	unlink(PF_DEP_CONFIG_FILR);
	os_dep_do_system("ralink_init", "rt2860_nvram_gen", NULL);
	os_dep_do_system("ralink_init", "rtdev_nvram_gen", NULL);
	os_dep_do_system("tar", "-cvf", PF_DEP_CONFIG_FILR, PF_DEP_2860_SETTING, PF_DEP_RTDEV_SETTING, NULL);
	strcpy(cfg_file, PF_DEP_CONFIG_FILR);
	unlink(PF_DEP_2860_SETTING);
	unlink(PF_DEP_RTDEV_SETTING);

	sysmgr_info("pf_dep_dump_cfg() cfg_file[%s] dump\n", cfg_file);

	return (eRET_SUCCESS);
}

e_ret pf_dep_load_cfg(char *cfg_file)
{
	int rc;
	e_ret ret = eRET_SUCCESS;

	rc = os_dep_do_system("tar", "-xvf", cfg_file, "-C", "/", NULL);
	if (rc != 0) {
		sysmgr_err("pf_dep_load_cfg() tar error rc:%d\n", rc);
		return (eRET_FAILURE);
	}
	ret = check_load_file_format(PF_DEP_2860_SETTING);
	if (ret != eRET_SUCCESS) {
		sysmgr_err("check_load_file_format() file:[%s] ret:%d\n", PF_DEP_2860_SETTING, ret);
		return ret;
	}
	ret = check_load_file_format(PF_DEP_RTDEV_SETTING);
	if (ret != eRET_SUCCESS) {
		sysmgr_err("check_load_file_format() file:[%s] ret:%d\n", PF_DEP_RTDEV_SETTING, ret);
		return ret;
	}

	os_dep_do_system("ralink_init", "clear", "rt2860", NULL);
	os_dep_do_system("ralink_init", "renew", "rt2860", PF_DEP_2860_SETTING, NULL);
	os_dep_do_system("ralink_init", "clear", "rtdev", NULL);
	os_dep_do_system("ralink_init", "renew", "rtdev", PF_DEP_RTDEV_SETTING, NULL);
	unlink(PF_DEP_2860_SETTING);
	unlink(PF_DEP_RTDEV_SETTING);
	unlink(cfg_file);

	sysmgr_info("pf_dep_load_cfg() cfg_file[%s] load\n", cfg_file);

	return (eRET_SUCCESS);
}

e_ret pf_dep_reset_cfg()
{
	os_dep_do_system("ralink_init", "clear", "rt2860", NULL);
	os_dep_do_system("ralink_init", "renew", "rt2860", PF_DEP_2860_DEFAULT_SETTING, NULL);
	os_dep_do_system("ralink_init", "clear", "rtdev", NULL);
	os_dep_do_system("ralink_init", "renew", "rtdev", PF_DEP_RTDEV_DEFAULT_SETTING, NULL);

	sysmgr_info("pf_dep_reset_cfg() done\n");

	return (eRET_SUCCESS);
}

e_ret pf_dep_set_device_mode(unsigned char mode)
{
#if 0
	char mode_str[2];
	unsigned char current_mode;

	if (mode > eDP_MODE_BRIDGE_REPEATER) {
		sysmgr_err("Invalid Operation Mode: [%d]\n", mode);
		return (eRET_INVALID_ARG);
	}

	pf_dep_get_device_mode(&current_mode);
	if (mode == current_mode) {
		return (eRET_SUCCESS);
	}

	mode_str[0] = mode + '0';
	mode_str[1] = 0;

	pf_dep_cfg_set_val(RT2860_NVRAM, DEVICE_OPERATION_MODE, mode_str);
#else
	dev_mode = mode;
#endif
	/* create a thread or proccess to run sleep and reboot.  return success now. */

	return (eRET_SUCCESS);

}

e_ret pf_dep_get_device_mode(unsigned char *mode)
{

#if 0
	const char *val;

	val = pf_dep_cfg_get_val(RT2860_NVRAM, DEVICE_OPERATION_MODE, DEFAULT_OPT_MODE);

	switch (val[0]) {
	case '0':
		*mode = eDP_MODE_ROUTER;
		break;

	case '1':
		*mode = eDP_MODE_BRIDGE_AP;
		break;

	case '2':
	default:
		*mode = eDP_MODE_BRIDGE_REPEATER;
		break;
	}
#else
	*mode = dev_mode;
#endif
	return (eRET_SUCCESS);

}

e_ret pf_dep_do_local_upgrade(tsys_admin * sa, char *fw_file)
{
	e_ret ret;
	ret = do_upgrade(sa, fw_file);
	if (ret != eRET_SUCCESS) {
		sysmgr_err("pf_dep_do_local_upgrade() [%s] err\n", fw_file);
		return ret;
	}

	return eRET_SUCCESS;
}

e_ret pf_dep_start_fota_check()
{
	int rc;
	pthread_t wgwt_tid;

	os_dep_mutex_init(&fm_download_mutex);
	sysmgr_dbg("pf_dep_download_fota_info() \n");
	rc = pthread_create(&wgwt_tid, NULL, do_check_fotainfo, NULL);
	usleep(1000);
	sysmgr_dbg("pthread_create() rc:%d.\n", rc);
	if (rc != 0) {
		sysmgr_err("pthread_create() failed, err: %d,[%s]\n", errno, strerror(errno));
		sysmgr_trace_exit();
		return (eRET_FAILURE);
	}

	return eRET_SUCCESS;
}

e_ret pf_dep_query_fota_check()
{
	int val;
	e_ret ret;

	val = 0;
	os_dep_mutex_lock(&fm_download_mutex);
	val = lock_fm;
	os_dep_mutex_unlock(&fm_download_mutex);
	switch (val) {
	case 1:
		ret = eRET_PENDDING;
		break;
	case 2:
		ret = eRET_SUCCESS;
		break;
	default:
		ret = eRET_FAILURE;
		break;
	}
	if (ret != eRET_PENDDING) {
		os_dep_mutex_lock(&fm_download_mutex);
		lock_fm = 1;
		os_dep_mutex_unlock(&fm_download_mutex);
		os_dep_mutex_destory(&fm_download_mutex);
	}
	sysmgr_dbg("pf_dep_query_fota_check() get download fotainfo status  ret[%d]\n", ret);

	return ret;
}

e_ret pf_dep_cancel_fota_check()
{
	int rc;

	rc = os_dep_do_system("killall", "wget", NULL);
	os_dep_mutex_lock(&fm_download_mutex);
	lock_fm = 1;
	os_dep_mutex_unlock(&fm_download_mutex);
	os_dep_mutex_destory(&fm_download_mutex);
	unlink(FW_INFO);
	if (rc != 0) {
		sysmgr_err("os_dep_do_system() killall wget[%s] rc:[%d]\n", FW_INFO, rc);
		return (eRET_FAILURE);
	}

	return eRET_SUCCESS;
}

e_ret pf_dep_start_fota_upgrade(tsys_admin * sa)
{
	int rc;
	pthread_t wgwt_tid;

	os_dep_mutex_init(&fm_download_mutex);
	sysmgr_dbg("pf_dep_download_fota_fm() \n");
	rc = pthread_create(&wgwt_tid, NULL, do_start_fota_upgrade, (void *)sa);
	sysmgr_dbg("pthread_create() rc:%d.\n", rc);
	if (rc != 0) {
		sysmgr_err("pthread_create() failed, err: %d,[%s]\n", errno, strerror(errno));
		sysmgr_trace_exit();
		return (eRET_FAILURE);
	}

	return eRET_SUCCESS;
}

e_ret pf_dep_query_fota_upgrade()
{
	int val;
	e_ret ret;

	val = 0;
	os_dep_mutex_lock(&fm_download_mutex);
	val = lock_fm;
	os_dep_mutex_unlock(&fm_download_mutex);

	switch (val) {
	case 1:
		ret = eRET_PENDDING;
		break;
	case 2:
		ret = eRET_SUCCESS;
		break;
	default:
		ret = eRET_FAILURE;
		break;
	}
	if (ret != eRET_PENDDING) {
		os_dep_mutex_lock(&fm_download_mutex);
		lock_fm = 1;
		os_dep_mutex_unlock(&fm_download_mutex);
		os_dep_mutex_destory(&fm_download_mutex);
	}
	sysmgr_dbg("pf_dep_query_fota_upgrade() get download fotafm status ret[%d]\n", ret);

	return ret;
}

e_ret pf_dep_cancel_fota_upgrade()
{
	int rc;

	rc = os_dep_do_system("killall", "wget", NULL);
	os_dep_mutex_lock(&fm_download_mutex);
	lock_fm = 1;
	os_dep_mutex_unlock(&fm_download_mutex);
	os_dep_mutex_destory(&fm_download_mutex);
	unlink(FW_NAME);
	if (rc != 0) {
		sysmgr_err("os_dep_do_system() killall wget[%s] rc:[%d]\n", FW_NAME, rc);
		return (eRET_FAILURE);
	}

	return eRET_SUCCESS;
}

e_ret pf_dep_do_fota_check(tsys_admin * sa)
{
	char tmp_buf[GET_LINE_BUF_SIZE];
	FILE *fp;
	tversion fota_info;
	e_ret ret;
	struct tm time_tm;

	if (NULL == (fp = fopen(FW_INFO, "ro"))) {
		sysmgr_err("fopen() file[%s] not found\n", FW_INFO);
		return (eRET_NOT_EXIST);
	}

	while (NULL != fgets(tmp_buf, GET_LINE_BUF_SIZE, fp)) {
		if (tmp_buf[0] == '\n' || tmp_buf[0] == '#')
			continue;
		if (!strncmp(tmp_buf, "Model:", 6)) {
			sscanf(tmp_buf, "Model: %s", fota_info.model);
		} else if (!strncmp(tmp_buf, "FW file:", 8)) {
			sscanf(tmp_buf, "FW file: %s", download_name_fw);
		} else if (!strncmp(tmp_buf, "FW version:", 11)) {
			sscanf(tmp_buf, "FW version: %s", fota_info.version);
		} else if (!strncmp(tmp_buf, "Release date:", 13)) {
			sysmgr_dbg("fota reltime is [%s]\n", tmp_buf);
			sscanf(tmp_buf, "Release date: %d-%d-%d", &time_tm.tm_year, &time_tm.tm_mon, &time_tm.tm_mday);
		}
	}

	fota_info.rel_time.year = time_tm.tm_year;
	fota_info.rel_time.month = time_tm.tm_mon;
	fota_info.rel_time.day = time_tm.tm_mday;

	ret = fm_info_check(sa, &fota_info);
	sa->fota_info = fota_info;

	fclose(fp);
	unlink(FW_INFO);
	return ret;
}

e_ret pf_dep_set_country(tdata_paths * dp, unsigned int country_number)
{
	int i;
	int rc;
	char iwpriv_arg[128];
	char var_region[8];
	tdp_if *dp_if;
	struct list_head *each;

	sysmgr_info("pf_dep_set_country() entry country_num[%u]\n", country_number);
	for (i = 0; i < NUM_OF_COUNTRIES; i++) {
		if (allCountry[i].CountryNum == country_number) {
			sysmgr_dbg("pf_dep_set_country() entry for all_num[%u]\n", allCountry[i].CountryNum);
			dp_if = NULL;
			list_for_each(each, &dp->all_ifs) {
				dp_if = list_entry(each, tdp_if, all_list);
				if (dp_if->type == eDP_IF_TYPE_WLAN24G_AP) {
					sprintf(iwpriv_arg, "%s=%s", WLAN_AP_COUNTRY_CODE, allCountry[i].IsoName);
					rc = do_iwpriv(dp_if->name, "set", iwpriv_arg);
					if (rc < 0) {
						return (eRET_FAILURE);
					}
					pf_dep_cfg_set_val(RT2860_NVRAM, WLAN_AP_COUNTRY_CODE, allCountry[i].IsoName);

					sprintf(var_region, "%u", allCountry[i].RegDomainNum11A);
					pf_dep_cfg_set_val(RT2860_NVRAM, WLAN_AP_COUNTRYREGIONFORABAND, var_region);

					sprintf(iwpriv_arg, "%s=%u", WLAN_AP_COUNTRYREGION,
						allCountry[i].RegDomainNum11G);
					rc = do_iwpriv(dp_if->name, "set", iwpriv_arg);
					if (rc < 0) {
						return (eRET_FAILURE);
					}
					sprintf(var_region, "%u", allCountry[i].RegDomainNum11G);
					pf_dep_cfg_set_val(RT2860_NVRAM, WLAN_AP_COUNTRYREGION, var_region);
					pf_dep_wlanap_reset(dp_if);
					((twlan_ap_if_linkcfg *) dp_if->linkcfg)->region =
					    allCountry[i].RegDomainNum11G;
				} else if (dp_if->type == eDP_IF_TYPE_WLAN5G_AP) {
					sprintf(iwpriv_arg, "%s=%s", WLAN_AP_COUNTRY_CODE, allCountry[i].IsoName);
					rc = do_iwpriv(dp_if->name, "set", iwpriv_arg);
					if (rc < 0) {
						return (eRET_FAILURE);
					}
					pf_dep_cfg_set_val(RTDEV_NVRAM, WLAN_AP_COUNTRY_CODE, allCountry[i].IsoName);

					sprintf(var_region, "%u", allCountry[i].RegDomainNum11A);
					pf_dep_cfg_set_val(RTDEV_NVRAM, WLAN_AP_COUNTRYREGIONFORABAND, var_region);

					sprintf(var_region, "%u", allCountry[i].RegDomainNum11G);
					pf_dep_cfg_set_val(RTDEV_NVRAM, WLAN_AP_COUNTRYREGION, var_region);

					pf_dep_wlanap_reset(dp_if);
					((twlan_ap_if_linkcfg *) dp_if->linkcfg)->region =
					    allCountry[i].RegDomainNum11A;
				}
			}
			break;
		}
	}
	if (i == NUM_OF_COUNTRIES) {
		return eRET_FAILURE;
	}

	sprintf(var_region, "%u", country_number);
	pf_dep_cfg_set_val(RT2860_NVRAM, WLAN_AP_COUNTRYNUM, var_region);

	return eRET_SUCCESS;
}

e_ret pf_dep_get_country(unsigned int *country_number)
{
	const char *val;

	val = pf_dep_cfg_get_val(RT2860_NVRAM, WLAN_AP_COUNTRYNUM, "");
	*country_number = strtol(val, NULL, 10);
	sysmgr_dbg("pf_dep_get_country_num() get [%u]\n", *country_number);

	return (eRET_SUCCESS);
}

e_ret check_load_file_format(char *filename)
{
	FILE *fp;
	int found;
	unsigned char buf[GET_LINE_BUF_SIZE];

	if (NULL == (fp = fopen(filename, "ro"))) {
		sysmgr_err("check_load_file_format() file[%s] not found\n", filename);
		return (eRET_NOT_EXIST);
	}

	found = 0;
	while (NULL != fgets(buf, GET_LINE_BUF_SIZE, fp)) {
		if (buf[0] == '\n' || buf[0] == '#')
			continue;
		if (!strncmp(buf, "Default\n", 8)) {
			found = 1;
			break;
		}
	}
	if (!found) {
		sysmgr_err("check_load_file_format() file[%s] format error!\n", filename);
		fclose(fp);
		return (eRET_FAILURE);
	}

	fclose(fp);
	return (eRET_SUCCESS);
}

e_ret set_tz_to_cfgfile(const unsigned int timezone)
{
	int fd;
	const char *val_tz;
	char tz_str[32];

	sysmgr_trace_enter();
	sysmgr_dbg("Check timezone is [%u] \n", timezone);
	switch (timezone) {
	case 0:
		val_tz = "UTC12";
		break;
	case 1:
		val_tz = "UTC11";
		break;
	case 2:
		val_tz = "UTC10";
		break;
	case 3:
		val_tz = "NAST9DST";
		break;
	case 4:
		val_tz = "PST8DST";
		break;
	case 5:
		val_tz = "MST7DST_1";
		break;
	case 6:
		val_tz = "MST7_2";
		break;
	case 7:
		val_tz = "MST7DST_3";
		break;
	case 8:
		val_tz = "CST6DST_1";
		break;
	case 9:
		val_tz = "CST6DST_2";
		break;
	case 10:
		val_tz = "CST6DST_3";
		break;
	case 11:
		val_tz = "CST6DST_3_1";
		break;
	case 12:
		val_tz = "UTC6";
		break;
	case 13:
		val_tz = "EST5DST";
		break;
	case 14:
		val_tz = "UTC5_1";
		break;
	case 15:
		val_tz = "UTC5_2";
		break;
	case 16:
		val_tz = "AST4DST";
		break;
	case 17:
		val_tz = "UTC4_1";
		break;
	case 18:
		val_tz = "UTC4DST_2";
		break;
	case 19:
		val_tz = "NST3.30DST";
		break;
	case 20:
		val_tz = "EBST3DST_1";
		break;
	case 21:
		val_tz = "UTC3";
		break;
	case 22:
		val_tz = "EBST3DST_2";
		break;
	case 23:
		val_tz = "NORO2DST";
		break;
	case 24:
		val_tz = "EUT1DST";
		break;
	case 25:
		val_tz = "UTC1";
		break;
	case 26:
		val_tz = "GMT0DST_1";
		break;
	case 27:
		val_tz = "GMT0DST_2";
		break;
	case 28:
		val_tz = "UTC-1DST_1";
		break;
	case 29:
		val_tz = "UTC-1_1_1";
		break;
	case 30:
		val_tz = "UTC-1_2";
		break;
	case 31:
		val_tz = "UTC-1_2_1";
		break;
	case 32:
		val_tz = "MET-1DST";
		break;
	case 33:
		val_tz = "MET-1DST_1";
		break;
	case 34:
		val_tz = "MEZ-1DST";
		break;
	case 35:
		val_tz = "MEZ-1DST_1";
		break;
	case 36:
		val_tz = "UTC-1_3";
		break;
	case 37:
		val_tz = "UTC-2DST";
		break;
	case 38:
		val_tz = "EST-2DST";
		break;
	case 39:
		val_tz = "UTC-2_1";
		break;
	case 40:
		val_tz = "UTC-2DST_2";
		break;
	case 41:
		val_tz = "IST-2DST";
		break;
	case 42:
		val_tz = "SAST-2";
		break;
	case 43:
		val_tz = "EET-2DST";
		break;
	case 44:
		val_tz = "UTC-3_1";
		break;
	case 45:
		val_tz = "UTC-3_2";
		break;
	case 46:
		val_tz = "IST-3DST";
		break;
	case 47:
		val_tz = "UTC-3.30DST";
		break;
	case 48:
		val_tz = "UTC-4_2";
		break;
	case 49:
		val_tz = "UTC-4_3";
		break;
	case 50:
		val_tz = "UTC-4_1";
		break;
	case 51:
		val_tz = "UTC-4DST_2";
		break;
	case 52:
		val_tz = "UTC-4.30";
		break;
	case 53:
		val_tz = "UTC-5";
		break;
	case 54:
		val_tz = "UTC-5.30_2";
		break;
	case 55:
		val_tz = "UTC-5.30_1";
		break;
	case 56:
		val_tz = "UTC-5.30";
		break;
	case 57:
		val_tz = "UTC-5.45";
		break;
	case 58:
		val_tz = "RFT-6DST";
		break;
	case 59:
		val_tz = "UTC-6_1";
		break;
	case 60:
		val_tz = "UTC-6";
		break;
	case 61:
		val_tz = "UTC-6.30";
		break;
	case 62:
		val_tz = "UTC-7";
		break;
	case 63:
		val_tz = "CST-8_2";
		break;
	case 64:
		val_tz = "CST-8";
		break;
	case 65:
		val_tz = "CST-8_1";
		break;
	case 66:
		val_tz = "SST-8";
		break;
	case 67:
		val_tz = "CCT-8";
		break;
	case 68:
		val_tz = "WAS-8DST";
		break;
	case 69:
		val_tz = "UTC-8DST";
		break;
	case 70:
		val_tz = "UTC-9_1";
		break;
	case 71:
		val_tz = "JST-9";
		break;
	case 72:
		val_tz = "CST-9.30DST";
		break;
	case 73:
		val_tz = "UTC-9.30";
		break;
	case 74:
		val_tz = "UTC-10_3";
		break;
	case 75:
		val_tz = "UTC-10_1";
		break;
	case 76:
		val_tz = "UTC-10_2";
		break;
	case 77:
		val_tz = "TST-10TDT";
		break;
	case 78:
		val_tz = "UTC-10_5";
		break;
	case 79:
		val_tz = "UTC-11_2";
		break;
	case 80:
		val_tz = "UTC-11";
		break;
	case 81:
		val_tz = "UTC-11_1";
		break;
	case 82:
		val_tz = "UTC-12";
		break;
	case 83:
		val_tz = "NZST-12DST";
		break;
	case 84:
		val_tz = "UTC-13";
		break;
	default:
		val_tz = "UCT_000";
		break;
	}

	fd = open(TIMEZONECFGFILE, O_CREAT | O_WRONLY | O_TRUNC | O_APPEND, 0666);
	if (fd < 0) {
		sysmgr_err("open(%s) failed, err: %d,[%s]\n", TIMEZONECFGFILE, errno, strerror(errno));
		return (eRET_FAILURE);
	}
	sprintf(tz_str, "%s\n", val_tz);
	write(fd, tz_str, strlen(tz_str));
	close(fd);

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret get_fm_info(char *fm_name, tversion * fw_info)
{
	FILE *fd;
	time_t timestamp;
	struct tm *p_tm;
	image_header_t header;
	image_header_t *hdr = &header;

	fd = fopen(fm_name, "r");
	if (fd == NULL) {
		sysmgr_err("get_fm_info() file[%s] not found\n", fm_name);
		return (eRET_FAILURE);
	}

	memset(hdr, 0, sizeof(*hdr));
	fread(hdr, sizeof(*hdr), 1, fd);
	timestamp = (time_t) ntohl(hdr->ih_time);
	p_tm = gmtime(&timestamp);
	fw_info->rel_time.year = p_tm->tm_year + 1900;
	fw_info->rel_time.month = p_tm->tm_mon + 1;
	fw_info->rel_time.day = p_tm->tm_mday;
	fw_info->rel_time.hour = p_tm->tm_hour;
	fw_info->rel_time.minute = p_tm->tm_min;
	fw_info->rel_time.second = p_tm->tm_sec;

	sscanf(hdr->ih_name, "%s %s", fw_info->model, fw_info->version);

	sysmgr_dbg("get_fm_info() fwname[%s], ver[%s] ,datetime[%d-%d-%d-%d:%d:%d]\n",
		   fw_info->model, fw_info->version, fw_info->rel_time.year, fw_info->rel_time.month,
		   fw_info->rel_time.day, fw_info->rel_time.hour, fw_info->rel_time.minute, fw_info->rel_time.second);

	fclose(fd);
	return (eRET_SUCCESS);
}

e_ret fm_info_check(tsys_admin * sa, tversion * fota_info)
{
	float ver_fm;
	float ver_fota;
	e_ret ret;

	sscanf(sa->fw_info.version, "V%f", &ver_fm);
	sscanf(fota_info->version, "V%f", &ver_fota);

	sysmgr_dbg("sa version is [%s] %f\n", sa->fw_info.version, ver_fm);
	sysmgr_dbg("fota version is [%s] %f\n", fota_info->version, ver_fota);
	sysmgr_dbg("sa model is [%s] \n", sa->fw_info.model);
	sysmgr_dbg("fota model is [%s] \n", fota_info->model);
	sysmgr_dbg("sa reltime is [%u-%u-%u %u:%u:%u] \n", sa->fw_info.rel_time.year, sa->fw_info.rel_time.month,
		   sa->fw_info.rel_time.day, sa->fw_info.rel_time.hour, sa->fw_info.rel_time.minute,
		   sa->fw_info.rel_time.second);
	sysmgr_dbg("fota reltime is [%u-%u-%u %u:%u:%u] \n", fota_info->rel_time.year, fota_info->rel_time.month,
		   fota_info->rel_time.day, fota_info->rel_time.hour, fota_info->rel_time.minute,
		   fota_info->rel_time.second);

	if (!strcmp(sa->fw_info.model, fota_info->model)) {
		if (ver_fota > ver_fm || (fota_info->rel_time.year > sa->fw_info.rel_time.year ||
					  fota_info->rel_time.month > sa->fw_info.rel_time.month ||
					  fota_info->rel_time.day > sa->fw_info.rel_time.day)) {
			ret = eRET_SUCCESS;
		} else {
			ret = eRET_ALREADY_EXIST;
		}
	} else {
		ret = eRET_ALREADY_EXIST;
	}
	sysmgr_dbg("fm_info_check() ret is [%d]\n", ret);

	return ret;
}

e_ret fm_upgrade_check(tsys_admin * sa, tversion * fota_info, char *fw_file)
{
	int ifd;
	int len;
	char *data;
	unsigned int checksum;
	unsigned char *ptr;
	image_header_t header;
	image_header_t *hdr = &header;
	struct stat sbuf;

#ifdef SYSMGR_FW_DO_MODULE_CHECK
	if (strcmp(sa->fw_info.model, fota_info->model)) {
		sysmgr_err("fm_upgrade_check() model error \n");
		return eRET_FAILURE;
	}
#endif /* SYSMGR_FW_DO_MODULE_CHECK */

	ifd = open(fw_file, O_RDONLY, 0666);
	if (ifd < 0) {
		sysmgr_err("fm_upgrade_check() Can't open %s: %s\n", fw_file);
		return eRET_FAILURE;
	}

	if (fstat(ifd, &sbuf) < 0) {
		sysmgr_err("fm_upgrade_check(): Can't stat \n");
		return eRET_FAILURE;
	}

	ptr = (unsigned char *)mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0);
	if (ptr == (unsigned char *)MAP_FAILED) {
		sysmgr_err("fm_upgrade_check(): Can't map \n");
		return eRET_FAILURE;
	}

	memcpy(hdr, ptr, sizeof(image_header_t));
	if (NTOHL(hdr->ih_magic) != IH_MAGIC) {
		sysmgr_err("fm_upgrade_check(): magic num err \n");
		return eRET_FAILURE;
	}

	data = (char *)hdr;
	len = sizeof(image_header_t);

	checksum = NTOHL(hdr->ih_hcrc);
	hdr->ih_hcrc = HTONL(0);
	sysmgr_dbg("fm_upgrade_check()head CRC is %u; checksum %u\n", crc32(0, data, len), checksum);
	if (crc32(0, data, len) != checksum) {
		sysmgr_err("fm_upgrade_check(); CRC head err\n");
		return eRET_FAILURE;
	}

	data = (char *)(ptr + sizeof(image_header_t));
	len = sbuf.st_size - sizeof(image_header_t);
	sysmgr_dbg("fm_upgrade_check()date CRC is %u; checksum %u\n", crc32(0, data, len), NTOHL(hdr->ih_dcrc));
	if (crc32(0, data, len) != NTOHL(hdr->ih_dcrc)) {
		sysmgr_err("fm_upgrade_check(); CRC date err\n");
		return eRET_FAILURE;
	}

	return eRET_SUCCESS;

}

e_ret mtd_write_firmware(char *filename, char *offset, char *len, char *mtdname)
{
	int rc;
	rc = os_dep_do_system("mtd_write", "-o", offset, "-l", len, "write", filename, mtdname, NULL);

	sysmgr_dbg("mtd_write_firmware() write [%s] err rc:[%d]\n", mtdname, rc);
	if (rc != 0) {
		sysmgr_err("mtd_write_firmware() write [%s] err rc:[%d]\n", mtdname, rc);
		return eRET_FAILURE;
	}

	return eRET_SUCCESS;
}

e_ret getFileSize(char *filename, int *len)
{
	int fd;
	struct stat StatBuf;
	if ((fd = open(filename, O_RDONLY, 0666)) == -1) {
		sysmgr_err("getFileSize() err\n");
	}
	if (fstat(fd, &StatBuf) == -1) {
		close(fd);
		sysmgr_err("getFileSize() get fstat err\n");
		return eRET_FAILURE;
	}
	close(fd);

	*len = StatBuf.st_size;
	return eRET_SUCCESS;
}

e_ret do_upgrade(tsys_admin * sa, char *fw_file)
{
	int len_fwfile;
	int len_kernel;
	int len_rootfs;
	char root_fs[32];
	char kernel[32];
	tversion fw_info;
	e_ret ret;

	ret = get_fm_info(fw_file, &fw_info);
	if (ret != eRET_SUCCESS) {
		sysmgr_err("get_fm_info() can't get [%s] fw info\n", fw_file);
		return ret;
	}

	ret = fm_upgrade_check(sa, &fw_info, fw_file);
	if (ret != eRET_SUCCESS) {
		sysmgr_err("fm_info_check() [%s] don't need upgrade\n", fw_file);
		return ret;
	}

	ret = getFileSize(fw_file, &len_fwfile);
	if (ret != eRET_SUCCESS) {
		sysmgr_err("getFileSize() [%s] can't get len\n", fw_file);
		return ret;
	}

	len_kernel = PF_DEP_MTD_KERNEL_PART_SIZ;
	sprintf(kernel, "%d", len_kernel);
	len_rootfs = len_fwfile - len_kernel;
	sprintf(root_fs, "%d", len_rootfs);

	ret = mtd_write_firmware(fw_file, "0", kernel, "Kernel");
	if (ret != eRET_SUCCESS) {
		sysmgr_err("mtd_write_firmware() [%s] write kernel err\n", fw_file);
		return ret;
	}

	ret = mtd_write_firmware(fw_file, kernel, root_fs, "RootFS");
	if (ret != eRET_SUCCESS) {
		sysmgr_err("mtd_write_firmware() [%s] write rootfs err\n", fw_file);
		return ret;
	}

	return eRET_SUCCESS;
}

void *do_check_fotainfo()
{
	int rc;

	sysmgr_trace_enter();

	os_dep_mutex_lock(&fm_download_mutex);
	lock_fm = 1;
	os_dep_mutex_unlock(&fm_download_mutex);

	sysmgr_dbg("wget %s -O %s\n", FW_INFO_URL, FW_INFO);
	rc = os_dep_do_system("wget", "-c", FW_INFO_URL, "-O", FW_INFO, NULL);
	if (rc != 0) {
		sysmgr_err("os_dep_do_system() wget can not get file[%s], rc:[%d]\n", FW_INFO_URL, rc);
	}

	os_dep_mutex_lock(&fm_download_mutex);
	if (rc != 0) {
		lock_fm = 0;
	} else {
		lock_fm = 2;
	}
	os_dep_mutex_unlock(&fm_download_mutex);

	sysmgr_trace_exit();
	pthread_exit(NULL);
}

void *do_start_fota_upgrade(void *arg)
{
	int rc;
	char ftp_url[PF_DEP_DOWNLOAD_URL_SIZE] = { 0 };
	tsys_admin *sa = (tsys_admin *) arg;
	e_ret ret;

	sysmgr_trace_enter();

	os_dep_mutex_lock(&fm_download_mutex);
	lock_fm = 1;
	os_dep_mutex_unlock(&fm_download_mutex);

	sprintf(ftp_url, "%s%s", FW_URL, download_name_fw);
	download_name_fw[0] = '\0';
	sysmgr_dbg("wget %s -O %s\n", ftp_url, FW_NAME);
	rc = os_dep_do_system("wget", "-c", ftp_url, "-O", FW_NAME, NULL);
	if (rc != 0) {
		sysmgr_err("os_dep_do_system() wget can not get file[%s], rc:[%d]\n", ftp_url, rc);
	}

	ret = do_upgrade(sa, FW_NAME);
	if (ret != eRET_SUCCESS) {
		sysmgr_err("do_upgrade() [%s] err\n", FW_NAME);
	}

	unlink(FW_NAME);

	os_dep_mutex_lock(&fm_download_mutex);
	if (rc != 0 || ret != eRET_SUCCESS) {
		lock_fm = 0;
	} else {
		lock_fm = 2;
	}
	os_dep_mutex_unlock(&fm_download_mutex);

	sysmgr_trace_exit();
	pthread_exit(NULL);
}
